package com.inspur.edp.udt.designtime.manager;


import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.inspur.edp.lcm.metadata.api.IMetadataContent;
import com.inspur.edp.lcm.metadata.spi.MetadataTransferSerializer;
import com.inspur.edp.udt.designtime.api.entity.ComplexDataTypeDef;
import com.inspur.edp.udt.designtime.api.entity.SimpleDataTypeDef;
import com.inspur.edp.udt.designtime.api.entity.UnifiedDataTypeDef;
import com.inspur.edp.udt.designtime.api.exception.UdtModelErrorCodeEnum;
import com.inspur.edp.udt.designtime.api.exception.UdtModelException;
import com.inspur.edp.udt.designtime.api.json.ComplexDataTypeDeserializer;
import com.inspur.edp.udt.designtime.api.json.ComplexDataTypeSerializer;
import com.inspur.edp.udt.designtime.api.json.SimpleDataTypeDeserializer;
import com.inspur.edp.udt.designtime.api.json.SimpleDataTypeSerializer;
import com.inspur.edp.udt.designtime.manager.services.UpdateElementService;

public class UdtManager implements MetadataTransferSerializer {

    private static final String TypePropertyName = "Type";
  private static final String ContentPropertyName = "Content";
  private static final String SimpleUdtType = "SimpleDataType";
  private static final String ComplexUdtType = "ComplexDataType";


  private String getSimpleUdtTypeJson(SimpleDataTypeDef simpleDataTypeDef) {
    ObjectMapper mapper = new ObjectMapper();
    SimpleModule module = new SimpleModule();
    module.addDeserializer(UnifiedDataTypeDef.class, new SimpleDataTypeDeserializer());
    module.addSerializer(UnifiedDataTypeDef.class, new SimpleDataTypeSerializer());
    mapper.registerModule(module);
    try {
      String sUdtJson = mapper.writeValueAsString(simpleDataTypeDef);
      return sUdtJson;
    } catch (JsonProcessingException e) {
      throw UdtModelException.createException(UdtModelErrorCodeEnum.GSP_BEMODEL_JSON_0004, e, "SimpleDataTypeDef");
    }
  }

  private String getComplexUdtTypeJson(ComplexDataTypeDef complexDataTypeDef) {
    ObjectMapper mapper = new ObjectMapper();
    SimpleModule module = new SimpleModule();
    module.addDeserializer(UnifiedDataTypeDef.class, new ComplexDataTypeDeserializer());
    module.addSerializer(UnifiedDataTypeDef.class, new ComplexDataTypeSerializer());
    mapper.registerModule(module);
    try {
      String cUdtJson = mapper.writeValueAsString(complexDataTypeDef);
      return cUdtJson;
    } catch (JsonProcessingException e) {
      throw UdtModelException.createException(UdtModelErrorCodeEnum.GSP_BEMODEL_JSON_0004, e, "ComplexDataTypeDef");
    }
  }

  private JsonNode serializeUdtContent(IMetadataContent metadataContent) {
    ObjectMapper mapper = new ObjectMapper();
    ObjectNode node = mapper.createObjectNode();
    if (metadataContent instanceof SimpleDataTypeDef) {
      String sUdtJson = getSimpleUdtTypeJson((SimpleDataTypeDef) metadataContent);
      node.put(TypePropertyName, SimpleUdtType);
      node.put(ContentPropertyName, sUdtJson);
    } else {
      String cUdtJson = getComplexUdtTypeJson((ComplexDataTypeDef) metadataContent);
      node.put(TypePropertyName, ComplexUdtType);
      node.put(ContentPropertyName, cUdtJson);

    }
    return node;

  }


  private IMetadataContent deSerializeUdtContent(ObjectNode node) {
    String type = node.get(TypePropertyName).textValue();
    String jsonContent = handleJsonString(node.get(ContentPropertyName).toString());
    UpdateElementService elementService = UpdateElementService.getInstance();
    switch (type) {
      case SimpleUdtType:
        SimpleDataTypeDef sUdt = getSUdtContent(jsonContent);
        sUdt.updateColumnsInfo();
        elementService.handleSimpleUdtChildAsso(sUdt);
        return sUdt;
      case ComplexUdtType:
        ComplexDataTypeDef cUdt = getCUdtContent(jsonContent);
        cUdt.updateColumnsInfo();
        elementService.handleComplexUdtChildAsso(cUdt);
        return cUdt;
      default:
        throw UdtModelException.createException(UdtModelErrorCodeEnum.GSP_BEMODEL_ENUM_NOTSUPPORT_0005, type);
    }
  }

  private SimpleDataTypeDef getSUdtContent(String jsonContent) {
    ObjectMapper mapper = new ObjectMapper();
    SimpleModule module = new SimpleModule();
    module.addDeserializer(UnifiedDataTypeDef.class, new ComplexDataTypeDeserializer());
    module.addSerializer(UnifiedDataTypeDef.class, new ComplexDataTypeSerializer());
    mapper.registerModule(module);
    try {
      SimpleDataTypeDef sUdt = mapper.readValue(jsonContent, SimpleDataTypeDef.class);
      return sUdt;
    } catch (JsonProcessingException e) {
      throw UdtModelException.createException(UdtModelErrorCodeEnum.GSP_BEMODEL_JSON_0001, e, "SimpleDataTypeDef");
    }
  }

  private ComplexDataTypeDef getCUdtContent(String jsonContent) {
    ObjectMapper mapper = new ObjectMapper();
    SimpleModule module = new SimpleModule();
    module.addDeserializer(UnifiedDataTypeDef.class, new ComplexDataTypeDeserializer());
    module.addSerializer(UnifiedDataTypeDef.class, new ComplexDataTypeSerializer());
    mapper.registerModule(module);
    try {
      ComplexDataTypeDef cUdt = mapper.readValue(jsonContent, ComplexDataTypeDef.class);
      return cUdt;
    } catch (JsonProcessingException e) {
      throw UdtModelException.createException(UdtModelErrorCodeEnum.GSP_BEMODEL_JSON_0001, e, "ComplexDataTypeDef");
    }
  }

  @Override
  public String serialize(IMetadataContent metadataContent) {
    String metadataJson = handleJsonString(serializeUdtContent(metadataContent).toString());
    return metadataJson;
  }

  @Override
  public IMetadataContent deserialize(String jsonContent) {
    ObjectMapper mapper = new ObjectMapper();
    try {
      JsonNode node = mapper.readTree(handleJsonString(jsonContent.toString()));
      IMetadataContent metadataContent = deSerializeUdtContent((ObjectNode) node);
      return metadataContent;
    } catch (JsonProcessingException e) {
      throw UdtModelException.createException(UdtModelErrorCodeEnum.GSP_BEMODEL_JSON_0001, e, "UdtContent");
    }
  }

  public final JsonNode Serialize(IMetadataContent metadataContent) {
    ObjectMapper mapper = new ObjectMapper();

    JsonNode node = null;
    try {
      node = mapper.readTree(handleJsonString(serializeUdtContent(metadataContent).toString()));
    } catch (JsonProcessingException e) {
      throw UdtModelException.createException(UdtModelErrorCodeEnum.GSP_BEMODEL_JSON_0004, e, "UdtContent");
    }
    return node;
  }

  public IMetadataContent DeSerialize(JsonNode jsonNode) {
    IMetadataContent metadataContent = deSerializeUdtContent((ObjectNode) jsonNode);
    return metadataContent;
  }
  ///#endregion

//C#
  ///#region 兼容关联子节点


  private static String handleJsonString(String contentJson) {
    if (!contentJson.startsWith("\"")) {
      return contentJson;
    }
    contentJson = contentJson.replace("\\r\\n", "");
    contentJson = contentJson.replace("\\\"{", "{");
    contentJson = contentJson.replace("}\\\"", "}");
    while (contentJson.startsWith("\"")) {
      contentJson = contentJson.substring(1, contentJson.length() - 1);
    }

    contentJson = contentJson.replace("\\\"", "\"");
    contentJson = contentJson.replace("\\\\", "");
    return contentJson;
  }

//C#
  ///#endregion

}